/**
 * 
 */
package com.baijia.tianxiao.connect.handler;

import java.io.IOException;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.PongMessage;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import com.alibaba.fastjson.JSON;
import com.baijia.tianxiao.connect.config.Constants;
import com.baijia.tianxiao.connect.enums.CloseReasonEnum;
import com.baijia.tianxiao.connect.route.api.enums.MsgType;
import com.baijia.tianxiao.connect.route.api.model.TxMessage;
import com.baijia.tianxiao.connect.service.BizMessageReceiveService;
import com.baijia.tianxiao.connect.util.TianxiaoConnectUtil;

/**
 * @author leiruiqi
 *
 */
public class TianxiaoWebSocketHandler extends TextWebSocketHandler{
	
    private static Logger logger = LoggerFactory.getLogger(TianxiaoWebSocketHandler.class); 

	@Resource
	private TianxiaoConnectUtil tianxiaoConnectUtil;
	
	@Resource
	private BizMessageReceiveService bizMessageReceiveService;
    

	public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
		
		CloseReasonEnum reasonEnum = CloseReasonEnum.getByName(closeStatus.getReason());
		
		String websocket_username = (String)session.getAttributes().get(Constants.SESSION_USERNAME);
		logger.info("CloseStatus ="+ closeStatus.getCode()+" ,sessionKey="+websocket_username+" reasonEnum="+reasonEnum);
		
		if(StringUtils.isNotBlank(websocket_username)){
			logger.info("current session id="+session.getId());
			WebSocketSession removedSession = TianxiaoConnectUtil.getSession(websocket_username);
			if(removedSession==null){
				logger.info("can not find session by websocket_username:"+websocket_username);
				return;
			}
			logger.info("find session id="+removedSession.getId());
			if(StringUtils.equals(removedSession.getId(),session.getId())){
				tianxiaoConnectUtil.removeSession(session);
				logger.info("remove webSocketSession username="+websocket_username+",result="+(removedSession!=null));
			}
			//手动关闭的如果给了closeReasonEnum，就是不需要通知解绑的，相反，链接超时等，需要通知cr解绑session的close则不给closeReasonEnum
			if(reasonEnum == null){
				tianxiaoConnectUtil.unbindSession(session);
			}
			
		}
		
	}

	public void afterConnectionEstablished(WebSocketSession session) throws Exception {

		String websocket_username = (String)session.getAttributes().get(Constants.SESSION_USERNAME);
		String deviceKey =  (String)session.getAttributes().get(Constants.BIZ_TYPE)+ (String)session.getAttributes().get(Constants.DEVICE_ID);
		session.getAttributes().put(Constants.LAST_MSG_TIME, System.currentTimeMillis());
		
		WebSocketSession existSession = TianxiaoConnectUtil.getSessionByDeviceKey(deviceKey);
		if(existSession!=null){
			logger.info("find exist session username=" + websocket_username);
		}
		
		if (existSession != null) {
			//existSession.close();
			TxMessage txMessage = getErrorReturnMessage("session time out");
			TianxiaoConnectUtil.closeSessionByReason(existSession, CloseReasonEnum.RECONNECT_LOCAL, JSON.toJSONString(txMessage));
			tianxiaoConnectUtil.addSession(websocket_username,deviceKey, session);
			tianxiaoConnectUtil.bindSession(session);
			logger.info("replace session username=" + websocket_username);
			
		} else {
			tianxiaoConnectUtil.addSession(websocket_username, deviceKey,session);
			tianxiaoConnectUtil.bindSession(session);
			logger.info("add new session username=" + websocket_username);
		}

		super.afterConnectionEstablished(session);
	}
	
	private TxMessage getErrorReturnMessage(String msg){
		TxMessage txMessage  = new TxMessage();
		txMessage.setType(MsgType.err.name());
		txMessage.setData(msg);
		return txMessage;
	}
	public void handleMessage(WebSocketSession session, WebSocketMessage<?> arg1) throws Exception {
		String wsuname = (String)session.getAttributes().get(Constants.SESSION_USERNAME);
		if(StringUtils.isBlank(wsuname)){
			TextMessage message = new TextMessage("no login");
			session.sendMessage(message);
			return;
		}
		WebSocketSession usersession = TianxiaoConnectUtil.getSession(wsuname);
		if(usersession!=null && StringUtils.equals(usersession.getId(), session.getId())){
			super.handleMessage(session, arg1);
		}
		
	}

	protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
		//logger.info("recieve message from session:"+session.getAttributes().get(Constants.SESSION_USERNAME)+",message:"+message);
		String messageStr = message.getPayload();
		
		TxMessage txMessage = null;
		try {
			txMessage = JSON.parseObject(messageStr, TxMessage.class);
		} catch (Exception e) {
			logger.error("JSON.parseObject exception",e);
			//throw new RuntimeException("Unexpected message ,can not tranport to JSON message: " + message);
			TextMessage returnmessage = new TextMessage("Unexpected message ,can not tranport to JSON message: "+message.getPayload());
			session.sendMessage(returnmessage);
			return;
		}
		
		String messagetype = txMessage.getType();
		if(StringUtils.isNoneBlank(messagetype)){
			session.getAttributes().put(Constants.LAST_MSG_TIME, System.currentTimeMillis());
		}else{
			return;
		}
		if(StringUtils.equals(messagetype, MsgType.ping.name())){
			return;
		}
		else if(StringUtils.equals(messagetype, MsgType.biz.name())){
			
			try {
				bizMessageReceiveService.doExcute(session, txMessage);
			} catch (Exception e) {
				logger.error("bizMessageReceiveService.doExcute exception ",e);
				String errorMsg = TianxiaoConnectUtil.buildTxMessageErr("","msg type="+messagetype+" not suport");
				TextMessage returnmessage = new TextMessage(errorMsg);
				session.sendMessage(returnmessage);
			}
			return;
		}
			
		else{
			String errorMsg = TianxiaoConnectUtil.buildTxMessageErr("","msg type="+messagetype+" not suport");
			TextMessage returnmessage = new TextMessage(errorMsg);
			session.sendMessage(returnmessage);
			return;	
		}
		
	}

	

	protected void handlePongMessage(WebSocketSession session, PongMessage message) throws Exception {
		System.out.println("receive pong ,user="+session.getAttributes().get(Constants.SESSION_USERNAME));
	}

	
	public void handleTransportError(WebSocketSession session, Throwable arg1) throws Exception {
		System.out.println("handleTransportError session="+session.getAttributes().get(Constants.SESSION_USERNAME));
	}

	public boolean supportsPartialMessages() {
		// TODO Auto-generated method stub
		return false;
	}

	/** 
     * 给某个用户发送消息 
     * 
     * @param userName 
     * @param message 
     */  
	public void sendMessageToUser(String userName, TextMessage message) {
		WebSocketSession userSession = TianxiaoConnectUtil.getSession(Constants.SESSION_USERNAME);
		if (userSession.getAttributes().get(Constants.SESSION_USERNAME).equals(userName)) {
			try {
				if (userSession.isOpen()) {
					userSession.sendMessage(message);
				}
			} catch (IOException e) {
				e.printStackTrace();
				logger.error("",e);
			}

		}

	}
	
	
}
